﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="AddFile.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   Defines the AddFile action to a list.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Collaboris.Saf.Actions.Wss.File
{
    using System.Collections.Generic;

    using Entities;

    using Engine;

    using SharePoint.Wss.Attributes;
    using SharePoint.Wss.Files;

    using Utils;

    using Microsoft.SharePoint;
    using Collaboris.SharePoint.Wss.Lists;

    [CollaborisClass(
        Title = "Add File",
        ReleaseStatus = ReleaseStatus.Beta,
        DisableDocumentation = false,
        ContactAuthorEmail = "Support@Collaboris.co.uk",
        Summary = "Adds a file to a list.",
        Remarks = @"If the destination file exists and 'FileIfExist' is 'True', the file will be removed before adding a new one.",
        ClassGuid = "{156E17A5-A7BA-4e1f-8A48-1BC341A7C642}",
        UndoImplemented = true
    )]
    public class AddFile : WSSActionBase<AddFileInfo>
    {
        #region Methods (6) 

        /// <summary>
        /// This method will add the file to a folder.
        /// </summary>
        /// <param name="context">
        /// </param>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <returns>
        /// </returns>
        protected override ProcessStatus DoAction(SafContext context, AddFileInfo entity)
        {
            this.Trace.TraceMethodStart("DoAction");

            ValidationHelper.VerifyObjectArgument(TargetWeb, "TargetWeb");
            ValidationHelper.VerifyObjectArgument(entity, "entity");

            ProcessStatus status = this.AddFileToFolder(entity, context.Web, ProcessMode.Do);

            this.Trace.TraceMethodEnd("DoAction");

            return status;
        }

        /// <summary>
        /// This method will "Undo" the Current file content.
        /// </summary>
        /// <param name="context">
        /// IContext defining the current context.
        /// </param>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <returns>
        /// ProcessStatus signalling to the Macro what its outcome was.
        /// </returns>
        protected override ProcessStatus UndoAction(SafContext context, AddFileInfo entity)
        {
            this.Trace.TraceMethodStart("UndoAction");
            
            ValidationHelper.VerifyObjectArgument(TargetWeb, "TargetWeb");
            ValidationHelper.VerifyObjectArgument(entity, "entity");

            ProcessStatus status = this.AddFileToFolder(entity, context.Web, ProcessMode.Undo);

            this.Trace.TraceMethodEnd("UndoAction");

            return status;
        }

        /// <summary>
        /// Checks the Data entity for Validity
        /// </summary>
        /// <param name="context">The <see cref="IContext"/>context.</param>
        /// <param name="entity">The data entity to Validate</param>
        /// <param name="errors">List of <see cref="ValidationError"/>s</param>
        /// <param name="mode"><see cref="ProcessMode"/> signalling wheter we are Doing, or Undoing the action.</param>
        /// <returns>false if invalid</returns>
        protected override bool IsValid(SafContext context, AddFileInfo entity, ref List<ValidationError> errors, ProcessMode mode)
        {
            int currentCount = errors.Count;

            // Validate each object now.            
            ValidateStringForNull(entity.FolderUrl, "AddFileInfo.FolderUrl", ref errors);
            ValidateStringForNull(entity.FileName, "AddFileInfo.FileName", ref errors);
            ValidateStringForNull(entity.FileDirectory, "AddFileInfo.FileDirectory", ref errors);                       
            
            // Have we added errors ?
            return errors.Count == currentCount;
        }

        /// <summary>
        /// Adds the specified the file as spec'd in <see cref="AddFileInfo"/>
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="web">The web.</param>
        /// <param name="mode">The mode.</param>
        /// <returns></returns>
        private ProcessStatus AddFileToFolder(AddFileInfo entity, SPWeb web, ProcessMode mode)
        {
            this.Trace.TraceMethodStart("AddFileToFolder");                        

            bool bSuccess = false;
            if (mode == ProcessMode.Do)
            {
                string fileUrl = SPFileHelper.AddFileToList(TargetWeb, 
                                                            entity.FolderUrl, 
                                                            entity.FileName, 
                                                            entity.FileDirectory,
                                                            entity.RemoveFileIfExist);
                if (!string.IsNullOrEmpty(fileUrl))
                {
                    bSuccess = true;
                    // Now populate the output property of the entity.
                    entity.FileUrl = fileUrl;
                    SPListItem listItem = TargetWeb.GetListItem(TargetWeb.Url + "/" + fileUrl);
                    if (listItem != null)
                    {
                        entity.ListName = listItem.ParentList.Title;
                        entity.ListItemID = listItem.ID;
                    }
                }
            }
            if (mode == ProcessMode.Undo)
            {
                bSuccess = SPFileHelper.RemoveFileFromList(TargetWeb, entity.FolderUrl, entity.FileName);
            }

            this.Trace.TraceMethodEnd("AddFileToFolder");

            if (bSuccess)
            {
                return ProcessStatus.Success;
            }
            else
            {
                return ProcessStatus.Error;
            }

        }

        #endregion Methods 
    }
}